/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sentry.exception;

import io.sentry.protocol.Mechanism;
import io.sentry.util.Objects;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

/**
 * A throwable decorator that holds an {@link io.sentry.protocol.Mechanism} related to the decorated
 * {@link Throwable}.
 *
 * @since 2021-06-02
 */
@ApiStatus.Internal
public final class ExceptionMechanismException extends RuntimeException {
    private static final long serialVersionUID = 142345454265713915L;
    private final @NotNull Mechanism exceptionMechanism;
    private final @NotNull Throwable throwable;
    private final @NotNull Thread thread;
    private final boolean snapshot;

    /**
     * A {@link Throwable} that decorates another with a Sentry {@link Mechanism}.
     *
     * @param mechanism The {@link Mechanism}.
     * @param throwable The {@link Throwable}.
     * @param thread The {@link Thread}.
     * @param snapshot if the captured {@link Thread}'s stacktrace is a snapshot.
     */
    public ExceptionMechanismException(
        final @NotNull Mechanism mechanism,
        final @NotNull Throwable throwable,
        final @NotNull Thread thread,
        final boolean snapshot) {
        exceptionMechanism = Objects.requireNonNull(mechanism, "Mechanism is required.");
        this.throwable = Objects.requireNonNull(throwable, "Throwable is required.");
        this.thread = Objects.requireNonNull(thread, "Thread is required.");
        this.snapshot = snapshot;
    }

    /**
     * A {@link Throwable} that decorates another with a Sentry {@link Mechanism}.
     *
     * @param mechanism The {@link Mechanism}.
     * @param throwable The {@link Throwable}.
     * @param thread The {@link Thread}.
     */
    public ExceptionMechanismException(
        final @NotNull Mechanism mechanism,
        final @NotNull Throwable throwable,
        final @NotNull Thread thread) {
        this(mechanism, throwable, thread, false);
    }

    /**
     * Returns the encapsulated Mechanism
     *
     * @return the Mechanism
     */
    public @NotNull Mechanism getExceptionMechanism() {
        return exceptionMechanism;
    }

    /**
     * Returns the encapsulated Throwable
     *
     * @return the Throwable
     */
    public @NotNull Throwable getThrowable() {
        return throwable;
    }

    /**
     * Returns the encapsulated Thread
     *
     * @return the Thread
     */
    public @NotNull Thread getThread() {
        return thread;
    }

    /**
     * Returns true if its a snapshot or false otherwise
     *
     * @return true or false
     */
    public boolean isSnapshot() {
        return snapshot;
    }
}
